package org.base.core.utils.shell;

import java.io.IOException;
import java.io.InputStream;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.jcraft.jsch.ChannelExec;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;

public class SSHClient {
	
	private static final Logger log = LoggerFactory.getLogger(SSHClient.class);
	
	private String hostname;
    private int port;
    private String username;
    private String password;
    
    public SSHClient(String hostname, int port, String username, String password) {
    	this.hostname = hostname;
    	this.port = port;
    	this.username = username;
    	this.password = password;
    }
    /**
     * 
     * @param command 执行命令
     * @param isWait 是否阻塞等待结果返回，最大阻塞时长120秒,不阻塞返回的code固定为-1
     * @return
     * @throws JSchException
     * @throws IOException
     */
    public SSHClientOutput execCommand(String command, boolean isWait) throws JSchException, IOException {
    	if(command.startsWith("rm")) {
    		throw new RuntimeException("删除指令,过滤");
    	}
    	int exitCode = -1;
    	Session session = newJSchSession();
        session.connect();
        
        ChannelExec channel = (ChannelExec) session.openChannel("exec");
		channel.setEnv("LANG", "zh_CN.UTF8");
		channel.setAgentForwarding(false);
		channel.setCommand(command);
		
		channel.setInputStream(null);
		InputStream in = channel.getInputStream();
		
		log.info(this.hostname + " try to execute commond: " + command);
		channel.connect();	
		StringBuffer text = new StringBuffer();
		//阻塞1秒，确保当前命令已发送出去
		try {
			Thread.sleep(1000);
		} catch (InterruptedException e1) {
		}
		if(isWait) {
			byte[] tmp = new byte[1024];
			//最大等待时长120秒
			int timeout = 120;
			while(true) {
				
				timeout--;
				while (in.available() > 0) {
		            int i = in.read(tmp, 0, 1024);
		            if (i < 0)
		                break;
		            String line = new String(tmp, 0, i);
		            text.append(line);
		        }
				if(channel.isClosed()) {
					if(in.available() > 0)
						continue;
					exitCode = channel.getExitStatus();
					log.info(this.hostname + " execute commond: " + command + " and the existCode is " + exitCode);
					break;
				}
				
				try {
					Thread.sleep(1000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				
				if(timeout<0) break;
			}
		}
		
		//关闭连接
		channel.disconnect();
        session.disconnect();
        
        return new SSHClientOutput(exitCode, text.toString());
    }
    
    private Session newJSchSession() throws JSchException {
        JSch jsch = new JSch();
        Session session = jsch.getSession(username, hostname, port);
        if (StringUtils.isNotBlank(password)) {
            session.setPassword(password);
        }
        session.setConfig("StrictHostKeyChecking", "no");
        return session;
    }
    
    public static class SSHClientOutput{
    	private String text;
        private int exitCode = -1;

        public SSHClientOutput(int exitCode, String text) {
            this.text = text;
            this.exitCode = exitCode;
        }


        public String getText() {
            return text.toString();
        }

        public int getExitCode() {
            return exitCode;
        }
    }

}
